import os
import re
import struct
import threading
import tkinter as tk
from tkinter import messagebox, filedialog,scrolledtext
import webbrowser
from tkinter import ttk
import time
from itertools import groupby
from numpy import array,savetxt

def loaddata(fp):
    binfile = open(fp, 'rb')
    binfile.seek(89)
    context = binfile.read(4)
    realContext = struct.unpack('2H', context)
    len = realContext[1] - realContext[0] + 1  # 计算光谱长度
    binfile2 = open(fp, 'rb')
    binfile2.seek(328)
    context2 = binfile2.read(4 * 2 * len)
    realContext = struct.unpack(str(len * 2) + 'f', context2)
    # realContext = struct.unpack('3874f', context2)
    realContext = list(realContext)
    wave = realContext[:len]
    specture = realContext[len:]
    return wave, specture


class AvaData:
    def __init__(self, fp):
        self.fp = fp
        w, v = loaddata(self.fp)
        self.wave = w
        self.value = v
        self.idx = self.spectrum_idx()

    def device_id(self):
        fn_no_ext = os.path.splitext(os.path.basename(self.fp))[0]
        return fn_no_ext.split("_")[0]

    def spectrum_idx(self):
        fn_no_ext = os.path.splitext(os.path.basename(self.fp))[0]
        ret = int(fn_no_ext.split("_")[1])
        return ret


def combine_same_idx(data: [AvaData]):
    sorted_val = sorted(data, key=lambda x: x.wave[0])
    wave, value = [], []
    for item in sorted_val:
        wave.extend(item.wave)
        value.extend(item.value)
    return wave, value


def combine(data: [AvaData]):
    # 使用 groupby 进行分组
    sorted_data = sorted(data, key=lambda x: x.spectrum_idx())
    idx_group_data = {key: list(group) for key, group in groupby(sorted_data, key=lambda x: x.spectrum_idx())}
    value = []
    add_header = False
    for idx, v_lst in idx_group_data.items():
        item_lst = list(v_lst)
        wave_item, value_item = combine_same_idx(v_lst)
        if (add_header == False):
            value.append(wave_item)
            add_header = True
        value.append(value_item)
    return array(value)


def decrypt(folder):
    pattern = re.compile(r'.*Raw8')
    match_files = [os.path.join(folder, f) for f in os.listdir(folder) if re.match(pattern, f)]
    datas = [AvaData(f) for f in match_files]
    return combine(datas).T


class MyUi:
    def __init__(self, root: tk.Tk):
        self.root = root
        self.init_menu()
        self.init_ui()

    def init_menu(self):
        window = self.root
        # 创建一个主目录菜单，也被称为顶级菜单
        main_menu = tk.Menu(window)
        main_menu.add_command(label="更新程序",
                              command=lambda: webbrowser.open("https://gitee.com/zhang_jie_sc/tools/releases"))
        window.configure(menu=main_menu)

    def init_ui(self):
        window = self.root
        # 初始化Entry控件的textvariable属性值
        self.select_path = tk.StringVar()

        # 布局控件
        tk.Label(root, text="文件路径：").grid( row=0,column=0,pady=2)
        tk.Entry(root, textvariable=self.select_path, width=25).grid( row=0,column=1,pady=2)
        tk.Button(root, text="选择文件夹", command=self.select_folder).grid(row=0, column=2,pady=2)

        self.btn_decryption = tk.Button(window, text="解密", command=self.decrtpt_data_thread, font=("Arial", 12))
        self.btn_decryption.grid(row=3, column=0, columnspan=3, pady=10)

        self.progress_bar = ttk.Progressbar(window, orient=tk.HORIZONTAL, length=300, mode='determinate')
        self.progress_bar.grid(row=4, column=0, columnspan=3, pady=10)
        self.output = scrolledtext.ScrolledText(window, width=50, height=20, font=("Arial", 12))
        self.output.grid(row=5, column=0, columnspan=3, pady=10, padx=10)

    def select_folder(self):
        # 文件夹选择
        selected_folder = filedialog.askdirectory()  # 使用askdirectory函数选择文件夹
        self.select_path.set(selected_folder)
        self.log(self.select_path.get()+"\n")

    def log(self, line):
        self.output.insert(tk.END, line)
        self.output.see(tk.END)

    def decrtpt_data(self):
        self.btn_decryption.configure(state=tk.DISABLED)
        folder_path=self.select_path.get()
        dirs = [os.path.join(folder_path, item) for item in os.listdir(folder_path) if
                  os.path.isdir(os.path.join(folder_path, item))]
        dirs=[f for f in dirs if 'log_' in os.path.basename(f)]
        self.output.delete(1.0, tk.END)
        self.progress_bar['maximum'] = len(dirs)
        self.progress_bar['value'] = 0

        total_start=time.perf_counter()
        output = self.output
        for folder in dirs:
            start_time=time.perf_counter()
            decrypt_data=decrypt(folder)
            basefolder = os.path.basename(folder)
            dest_dir=os.path.join(folder_path,'decryption',basefolder)
            if not os.path.exists(dest_dir):
                os.makedirs(dest_dir)
            dest_fp=os.path.join(dest_dir,'Times_0.csv')
            savetxt(dest_fp,decrypt_data,fmt='%.04f',delimiter=',')
            end_time = time.perf_counter()
            output.insert(tk.END, '{0} {1}秒\n'.format(basefolder,round(end_time-start_time,2)))
            output.see(tk.END)
            self.progress_bar['value'] += 1
            self.root.update_idletasks()
        total_end = time.perf_counter()
        output.insert(tk.END, '共耗时:{0}秒\n'.format(round(total_end - total_start, 2)))
        output.see(tk.END)
        self.btn_decryption.configure(state=tk.NORMAL)

    def decrtpt_data_thread(self):
        thread1 = threading.Thread(target=self.decrtpt_data)
        thread1.start()


# pyinstaller -F -w -i .\img\decryption.ico -n decryption .\decryption_ui.py
if __name__ == '__main__':
    root = tk.Tk()
    root.title("光谱数据解析软件")
    root.geometry("480x510")
    ui = MyUi(root)
    root.mainloop()